% def get_node_kind(mnemonic)
%   return "#{mnemonic.gsub('.', '_').upcase}"
% end
%
% def get_format_name(mnemonic)
%   return "#{mnemonic.gsub('.', '_').upcase}" + "_FORMATS"
% end
/**
 * Copyright (c) 2021-2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// Autogenerated file -- DO NOT EDIT!

#ifndef ES2PANDA_COMPILER_GEN_IR_ISA_H
#define ES2PANDA_COMPILER_GEN_IR_ISA_H

#include "ir/irnode.h"
#include "generated/formats.h"
#include "assembly-ins.h"

namespace ark::es2panda::compiler {
class Label : public IRNode {
public:
    explicit Label(const ir::AstNode* node, std::string id) : IRNode(node), id_(std::move(id)) {}

    static constexpr std::string_view PREFIX = "LABEL_";

    Formats GetFormats() const override
    {
        return Span<const Format>(nullptr, nullptr);
    }

    const std::string &Id() const
    {
        return id_;
    }

    size_t Registers([[maybe_unused]] std::array<VReg*, MAX_REG_OPERAND>* regs) override
    {
        return 0;
    }

    size_t Registers([[maybe_unused]] std::array<const VReg*, MAX_REG_OPERAND>* regs) const override
    {
        return 0;
    }

    size_t OutRegisters([[maybe_unused]] std::array<OutVReg, MAX_REG_OPERAND>* regs) const override
    {
        return 0;
    }

    void Transform(pandasm::Ins *ins, [[maybe_unused]] ProgramElement *programElement,
                   [[maybe_unused]] uint32_t totalRegs) const override
    {
        ins->opcode = pandasm::Opcode::INVALID;
        ins->setLabel = true;
        ins->label = id_;
    }

private:
    std::string id_;
};

// NOLINTBEGIN(readability-identifier-naming)
% def insn2node(insn)
%   mnemonic = insn.mnemonic.split('.')
%   return mnemonic.map{|el| el == '64' ? 'Wide' : el.capitalize}.join()
% end
%
% def get_ctor_args(insn)
%     ops = Array.new
%     ctor_args = Array.new
%     op_map = Hash.new { |h, k| h[k] = [] }
%
%     insn.operands.map do |operand|
%       name = operand.name
%       param_name = name
%       if operand.reg?
%         param_name = "#{name}#{op_map['reg'].size}"
%         op_map['reg'].push("#{param_name}_")
%         op_map['dreg'].push(["#{param_name}_", operand.type]) if operand.dst?
%         op_map['dreg'].push([nil, nil]) unless operand.dst?
%         type = 'VReg'
%       elsif operand.imm?
%         if insn.jump?
%           op_map['lbl'].push("#{name}_")
%           type = 'Label*'
%         else
%           param_name = "#{name}#{op_map['imm'].size}"
%           op_map['imm'].push("#{param_name}_")
%           type = operand.type == 'f64' ? 'double' : operand.type == 'f32' ? 'float' : 'int64_t'
%         end
%       elsif operand.id?
%         param_name = 'string_id'
%         op_map['str'].push("#{param_name}_")
%         type = 'util::StringView'
%       end
%       ops.push(param_name)
%       ctor_args.push("#{type} #{param_name}")
%     end
%     return ops,ctor_args,op_map
% end
%
% Panda::instructions.group_by(&:mnemonic).each do |mnemonic, group|
% insn = group.first
% node_kind = get_node_kind(mnemonic)
% class_name = insn2node(insn)
% base_class = "IRNode"
% ops_list,ctor_arg_list,op_map = get_ctor_args(insn)
% ctor_args = "const ir::AstNode* node" + (ctor_arg_list.length == 0 ? "" : ", ") + ctor_arg_list.map {|arg| "#{arg}"}.join(", ")
% members = ctor_arg_list.map {|arg| "#{arg}_;"}.join("\n    ")
% registers = op_map['reg'].map {|reg| "&#{reg}"}.join(", ")
% ops = (ops_list.length == 0 ? "" : ", ") + ops_list.map { |op| "#{op}_(#{op})"}.join(", ")
class <%= class_name %> : public <%= base_class %>
{
public:
    explicit <%= class_name %>(<%= ctor_args %>) : <%= base_class %>(node)<%= ops %>
    {
% insn.operands.each do |operand|
%   if operand.id? && operand.name != :string_id
        ES2PANDA_ASSERT(!string_id.Empty());
%   end
% end
    }

    Formats GetFormats() const override
    {
        return Span<const Format>(<%= get_format_name(insn.mnemonic) %>);
    }

    size_t Registers([[maybe_unused]] std::array<VReg*, MAX_REG_OPERAND>* regs) override
    {
% reg_cnt = 0
% for reg in op_map['reg']
        (*regs)[<%= reg_cnt %>] = &<%= reg %>;
%   reg_cnt+=1;
% end
        return <%= reg_cnt %>;
    }

    size_t Registers([[maybe_unused]] std::array<const VReg*, MAX_REG_OPERAND>* regs) const override
    {
% reg_cnt = 0
% for reg in op_map['reg']
        (*regs)[<%= reg_cnt %>] = &<%= reg %>;
%   reg_cnt+=1;
% end
        return <%= reg_cnt %>;
    }

    size_t OutRegisters([[maybe_unused]] std::array<OutVReg, MAX_REG_OPERAND>* regs) const override
    {
% reg_cnt = 0
%
% def type_to_enum(type)
%   return 'REF' if type == 'ref'
%   return 'ANY' if type == 'any'
%   return 'B64' if type == 'f64' || type == 'i64' || type == 'b64'
%   return 'B32'
% end
% for reg, type in op_map['dreg']
%   if reg
        (*regs)[<%= reg_cnt %>] = {&<%= reg %>, OperandType::<%= type_to_enum(type) %>};
%   elsif
        (*regs)[<%= reg_cnt %>] = {nullptr, OperandType::NONE};
%   end
%   reg_cnt+=1;
% end
        return <%= reg_cnt %>;
    }

    void Transform(pandasm::Ins *ins, [[maybe_unused]] ProgramElement *programElement,
                   [[maybe_unused]] uint32_t totalRegs) const override {
      ins->opcode = pandasm::Opcode::<%= node_kind %>;
% if op_map['reg'].length != 0
      ins->regs.reserve(<%= op_map['reg'].length %>);
% end
% if op_map['imm'].length != 0
      ins->imms.reserve(<%= op_map['imm'].length %>);
% end
% if op_map['str'].length + op_map['lbl'].length != 0
      ins->ids.reserve(<%= op_map['str'].length + op_map['lbl'].length %>);
% end
% for reg in op_map['reg']
      ins->regs.emplace_back(MapRegister(<%= reg %>.GetIndex(), totalRegs));
% end
% for imm in op_map['imm']
      ins->imms.emplace_back(<%= imm %>);
% end
% if insn.properties.include? 'literalarray_id' and insn.properties.none? 'skip_literal_id_patch'
      programElement->LiteralBufferIns().push_back(ins);
%end
% for str in op_map['str']
      std::string <%= str %>mutf8 = <%= str %>.Mutf8();
      ins->ids.emplace_back(<%= str %>mutf8);
      programElement->Strings().insert(std::move(<%= str %>mutf8));
% end
% for lbl in op_map['lbl']
      ins->ids.emplace_back(<%= lbl %>->Id());
% end
    }

% if ops_list.length != 0
private:
    <%= members %>
% end
};

% end
// NOLINTEND(readability-identifier-naming)
}  // namespace ark::es2panda::compiler

#endif
